package cn.wolfcode.wolf2w.service.impl;

import cn.wolfcode.wolf2w.domain.FansFollow;
import cn.wolfcode.wolf2w.domain.RegistParamDomain;
import cn.wolfcode.wolf2w.domain.UserInfo;
import cn.wolfcode.wolf2w.exception.LogicException;
import cn.wolfcode.wolf2w.redis.service.IUserInfoRedisService;
import cn.wolfcode.wolf2w.repository.UserInfoRepository;
import cn.wolfcode.wolf2w.service.IUserInfoService;
import cn.wolfcode.wolf2w.util.AssertUtil;
import cn.wolfcode.wolf2w.util.Consts;
import cn.wolfcode.wolf2w.util.EncryptionUtil;
import cn.wolfcode.wolf2w.util.RedisKeysStandard;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class UserInfoServiceImpl implements IUserInfoService {
    @Autowired
    private UserInfoRepository userInfoRepository;
    @Autowired
    private IUserInfoRedisService userInfoRedisService;
    @Autowired
    private Environment environment;
////    @Value("${sms.url}")
//    private String url;
//    @Value("${sms.appkey}")
//    private String appkey;

    @Override
    public void save(UserInfo userInfo) {
        userInfo.setId(null);
        userInfoRepository.save(userInfo);
    }

    @Override
    public void update(UserInfo userInfo) {
        userInfoRepository.save(userInfo);
    }

    @Override
    public void delete(String id) {
        userInfoRepository.deleteById(id);
    }

    @Override
    public UserInfo get(String id) {
        return userInfoRepository.findById(id).orElse(null);
    }

    @Override
    public List<UserInfo> listAll() {
        return userInfoRepository.findAll();
    }

    @Override
    public boolean findByPhone(String phone) {
        UserInfo user = userInfoRepository.findByPhone(phone);
        return user != null;
    }

    @Override
    public void sedVerifyCode(String phone) {
        String url = environment.getProperty("sms.url");
        String appkey =environment.getProperty("sms.appkey");
        System.out.println(url + "==========" + appkey);
        // 获取redis中缓存的发送次数记录  如果记录为空就创建，不为空则继续走下面的代码
        String value = userInfoRedisService.getVerifyCodeFreq(RedisKeysStandard.VERIFY_CODE_FREQ.addKeyMessage(phone));
        if (value == null) {
            //创建存储记录：发送的次数，5次之后需要分钟后才能发（使用redis存储次数）
            userInfoRedisService.cacheVerifyCodeFreq(RedisKeysStandard.VERIFY_CODE_FREQ.addKeyMessage(phone), Consts.VERIFY_CODE_FREQ + "", RedisKeysStandard.VERIFY_CODE_FREQ.getTime());
        }else {
            // 对redis中的信息发送频率缓存 减1并重置时间
            int num = Integer.valueOf(value); //当前的次数
            if (num <= 1){
                throw new LogicException("操作过于频繁，请5分钟之后再尝试");
            }
            userInfoRedisService.cacheVerifyCodeFreq(RedisKeysStandard.VERIFY_CODE_FREQ.addKeyMessage(phone), (Integer.valueOf(value) - 1) + "", RedisKeysStandard.VERIFY_CODE_FREQ.getTime());
        }
        //1.生成手机验证码
        String code = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 4);
        //2.根据验证码生成手机短信信息并发送到手机
        StringBuilder sb = new StringBuilder();
        sb.append("【狼行天下】你的注册验证码为：").append(code).append("  请在").append(Consts.VERIFY_CODE_VAI_TIME).append("分钟内使用");
        // 模拟发送信息
        System.err.println(sb.toString());

        // 真实发送信息
        //发送http请求的类
//        RestTemplate restTemplate = new RestTemplate();
//        // 参数1：api地址，参数2：返回结果数据的封装类型
//        // 参数3：携带的参数
//        String result = restTemplate.getForObject(url, String.class, phone, sb.toString(), appkey);
//        System.out.println(result);
//        if (!result.contains("SUCCESS")){
//            throw new LogicException("验证码发送失败");
//        }
        //3.redis存储验证码信息
//        String key = "verify_code:" + phone;
        userInfoRedisService.cacheVerifyCode(RedisKeysStandard.VERIFY_CODE.addKeyMessage(phone), code, RedisKeysStandard.VERIFY_CODE.getTime());

    }

    @Override
    public void regist(RegistParamDomain params) {
        // 参数判空
        AssertUtil.hasLength(params.getPhone(),"手机号不能为空");
        AssertUtil.hasLength(params.getNickname(),"昵称不能为空");
        AssertUtil.hasLength(params.getPassword(),"密码不能为空");
        AssertUtil.hasLength(params.getRpassword(),"确认密码不能为空");
        // 判断两次输入的密码是否正确
        AssertUtil.isEquals(params.getPassword(),params.getRpassword(),"两次输入密码不一致");
        AssertUtil.hasLength(params.getVerifyCode(),"验证码不能为空");
        // 判断手机号格式是否正确
        String regex = "^1[3-9][0-9]{9}$";
        if (!params.getPhone().matches(regex)){
            throw new LogicException("手机格式不正确");
        }
        // 密码加密
        params.setPassword(EncryptionUtil.encrypt(params.getPassword(),params.getPhone()));

        // 判断手机号的唯一性
        if (findByPhone(params.getPhone())) {
            throw new LogicException("手机号已注册");
        }
        // 判断短信是否一致
        String code = userInfoRedisService.getVerifyCode(RedisKeysStandard.VERIFY_CODE.addKeyMessage(params.getPhone()));
        AssertUtil.isEquals(code, params.getVerifyCode(),"验证码错误");
        // 注册
        UserInfo userInfo = new UserInfo();
        userInfo.setPhone(params.getPhone());
        userInfo.setNickname(params.getNickname());
        userInfo.setPassword(params.getPassword());
        userInfo.setEmail("");
        userInfo.setCity("");
        userInfo.setHeadImgUrl("/images/default.jpg");
        userInfo.setInfo("");
        userInfo.setState(UserInfo.STATE_NORMAL);
        userInfoRepository.save(userInfo);
    }

    @Override
    public Map<String, Object> login(String username, String password) {
        // 登录数据的合法性判断
        AssertUtil.hasLength(username, "用户名不能为空");
        AssertUtil.hasLength(password, "密码不能为空");
        //1. 判断用户的数据是否正确（查库）
        UserInfo user = userInfoRepository.findByPhone(username);
        // 进行密码判断之前需要对密码再次加密
        password = EncryptionUtil.encrypt(password, username);
        if (user == null || !user.getPassword().equals(password)){
            throw new LogicException("登录失败！账号或密码错误");
        }
        //2. 通过UUID创建用户的token令牌
        String token = UUID.randomUUID().toString().replaceAll("-", "");
        //3. 存入redis数据库中缓存起来（key：token， value：用户对象，存活时间30分钟）
        userInfoRedisService.cacheUserToken(RedisKeysStandard.USER_TOKEN.addKeyMessage(token), JSON.toJSONString(user),RedisKeysStandard.USER_TOKEN.getTime());
        //4. 把token与user对象以JsonResult的形式传到前端处理
        Map<String, Object> map = new HashMap<>();
        map.put("token",token);
        map.put("user",user);
        return map;
    }

    @Override
    public List<UserInfo> findByCity(String city) {

        return userInfoRepository.findByCity(city);
    }

    @Override
    public List<UserInfo> findById(List<String> ids) {
        List<UserInfo> list = new ArrayList<>();
        for (String id : ids) {
            list.add(this.get(id));
        }
        return list;
    }
}
